import { Agent } from "./libs/Agent";
import { RVOSimulator } from "./libs/RVOSimulator";
import { Vector2 } from "./libs/Vector2";

const { ccclass, property } = cc._decorator;

const _v2 = new Vector2();

@ccclass
export default class RvoMoveComp extends cc.Component {
    public destPosition: cc.Vec2 = cc.Vec2.ZERO;
    private _agent: Agent = null;
    get agent(): Agent {
        return this._agent;
    }
    set agent(value: Agent) {
        this._agent = value;
    }
    private _speed: number = 100;
    private _isGray: boolean = false;

    onLoad() {
        this.addAgent();
    }

    protected update(dt: number): void {
        if (this._agent) {
            _v2.x_ = this.destPosition.x; _v2.y_ = this.destPosition.y;
            if (_v2.sub(this._agent.position_).absSq() < 4) {
                this._agent.prefVelocity_.set(0, 0);
            } else {
                _v2.normalize().mulScalar(this._speed);
                this._agent.prefVelocity_.set(_v2);
            }
        }
    }

    private onSyncPosition() {
        this.node.setPosition(this._agent.position_.x_, this._agent.position_.y_);
    }

    public syncPositionToAgent() {
        if (this._agent) {
            this._agent.position_.x_ = this.node.x;
            this._agent.position_.y_ = this.node.y;
        }
    }

    protected onEnable(): void {
        this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
    }

    protected onDisable(): void {
        this.node.off(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
    }

    private onTouchEnd() {
        this._isGray = !this._isGray;
        this.setGray(this._isGray);

        this._isGray ? this.removeAgent() : this.addAgent();
    }

    private setGray(isGray: boolean) {
        let sprite = this.node.getComponent(cc.Sprite);
        if (this._isGray) {
            sprite.setMaterial(0, cc.MaterialVariant.getBuiltinMaterial("2d-gray-sprite"));
        } else {
            sprite.setMaterial(0, cc.MaterialVariant.getBuiltinMaterial("2d-sprite"));
        }
    }

    private addAgent() {
        this._agent = RVOSimulator.getInstance().addAgent(new Vector2(this.node.x, this.node.y), 10, this._speed, 30);
        this._agent.syncCallback = this.onSyncPosition;
        this._agent.syncTarget = this;
    }

    private removeAgent() {
        RVOSimulator.getInstance().removeAgent(this._agent);
        this._agent = null;
    }

    protected onDestroy(): void {
        this.removeAgent();
    }
}
